package com.tsd.jxc.stock.service.impl;

import com.tsd.base.BaseCodeRuleConstants;
import com.tsd.base.service.BaseCodeRuleService;
import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.service.GetDuplicatedObj;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.config.JxcCodeRuleConstants;
import com.tsd.jxc.stock.StockConstants;
import com.tsd.jxc.stock.dao.JxcStockInventoryItemMapper;
import com.tsd.jxc.stock.dao.JxcStockInventoryMapper;
import com.tsd.jxc.stock.entity.*;
import com.tsd.jxc.stock.job.JxcStockJob;
import com.tsd.jxc.stock.service.*;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import com.tsd.system.entity.SysUserExt;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 描述：JxcStockInventory 服务实现层
 *
 * @author Hillpool
 * @date 2022/07/29 15:06:33
 */
@Service
public class JxcStockInventoryServiceImpl extends BaseServiceImpl implements JxcStockInventoryService, GetDuplicatedObj {

    @Resource
    private JxcStockInventoryMapper jxcStockInventoryMapper;
    @Resource
    private JxcStockInventoryItemMapper jxcStockInventoryItemMapper;
    @Resource
    private JxcStockInventoryItemService jxcStockInventoryItemService;
    @Resource
    private JxcStockGoodsService jxcStockGoodsService;
    @Resource
    private BaseCodeRuleService baseCodeRuleService;
    @Resource
    private JxcStockInbillService jxcStockInbillService;
    @Resource
    private JxcStockOutbillService jxcStockOutbillService;
    @Resource
    private JxcStockJob jxcStockJob;

    @Override
    public JxcStockInventory getJxcStockInventoryById(Long id) throws Exception {
        return jxcStockInventoryMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcStockInventoryExt queryBySid(String sid) throws Exception {
        JxcStockInventoryExt inventoryExt = jxcStockInventoryMapper.selectBySid(sid);
        if (inventoryExt != null) {
            List<JxcStockInventoryItemExt> itemExtList = jxcStockInventoryItemService.queryByInventoryList(Collections.singletonList(inventoryExt.getSid()));
            inventoryExt.setItem_list(itemExtList);
        }
        return inventoryExt;
    }

    @Override
    public void deleteJxcStockInventorys(List<String> list, SysUser opUser) throws Exception {
        if (HlpUtils.isEmptyList(list)) {
            return;
        }
        BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
        logicVo.setSidList(list);
        jxcStockInventoryMapper.deleteLogicBySidList(logicVo);
        // 删除明细
        jxcStockInventoryItemMapper.deleteLogicByInventoryList(logicVo);
    }

    @Override
    public boolean isDuplicated(Object obj, String code) {
        if (obj == null) {
            return false;
        }
        JxcStockInventoryExt inventoryExt = (JxcStockInventoryExt) obj;
        inventoryExt.setCode(code);
        return jxcStockInventoryMapper.selectDuplicatedCode(inventoryExt) != null;
    }

    @Override
    public void saveJxcStockInventory(JxcStockInventoryExt record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            if (!HlpUtils.isEmpty(record.getCode())) {
                //如果是手动设置了编号，则检查是否有相同的，有的话，置空后重新生成
                JxcStockInventoryExt same = jxcStockInventoryMapper.selectDuplicatedCode(record);
                if (same != null) {
                    record.setCode(null);
                }
                record.setUpdate_stock(0);
            }
            if (HlpUtils.isEmpty(record.getCode())) {
                String genCode = baseCodeRuleService.genCode(null, JxcCodeRuleConstants.TYPE_JXC_STOCK_INVENTORY, JxcCodeRuleConstants.TYPE_NAME_JXC_STOCK_INVENTORY, opUser, record.getCode(), record, this);
                record.setCode(genCode);
            }
            if (HlpUtils.isEmpty(record.getState())) {
                record.setState(0);
            }
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE, new Date(), record.getCheck_date());
            jxcStockInventoryMapper.insertSelective(record);
        } else {
            JxcStockInventoryExt same = jxcStockInventoryMapper.selectDuplicatedCode(record);
            if (same != null) {
                throw new HlpException("已存在相同编号的记录");
            }
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            super.updateYyyyMmdd(record, record.getCheck_date());
            jxcStockInventoryMapper.updateByPrimaryKeySelective(record);
        }
        jxcStockInventoryItemService.saveJxcStockInventoryDetail(record, opUser);
    }

    @Override
    public List<JxcStockInventoryExt> findJxcStockInventorys(Map<String, Object> params, PageBean page) throws Exception {
        return jxcStockInventoryMapper.selectByPage(params, page);
    }

    @Override
    public List<JxcStockInventoryExt> findJxcStockInventorys(Map<String, Object> params) throws Exception {
        return jxcStockInventoryMapper.selectByParams(params);
    }

    @Override
    public List<JxcStockInventoryExt> selectInventoryByPage(Map<String, Object> params, PageBean page) throws Exception {
        return jxcStockInventoryMapper.selectInventoryByPage(params, page);
    }

    @Override
    public void auditJxcStockInventory(List<String> record, SysUser opUser, Integer state) throws Exception {
        for (String sid : record) {
            JxcStockInventoryExt itemExt = this.queryBySid(sid);
            itemExt.setState(state);
            if (state == 2) {
                super.autoInjectBaseData(itemExt, opUser, this.TYPE_UPDATE_STOCK);
            } else {
                super.autoInjectBaseData(itemExt, opUser, this.TYPE_AUDIT);
            }
            jxcStockInventoryMapper.auditJxcStockInventory(itemExt);
        }
    }

    @Override
    public void changeJxcStockInventoryAuditState(List<String> sidList, Integer state, SysUserExt opUser) throws Exception {
        JxcStockInventoryExt params = new JxcStockInventoryExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcStockInventoryExt> billExtList = jxcStockInventoryMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(billExtList)) {
            return;
        }

        for (JxcStockInventoryExt inventoryExt : billExtList) {
            if (state == 1) {
                inventoryExt.setState(StockConstants.STATE_AUDITED);
                inventoryExt.setAuditor_sid(opUser.getSid());
                inventoryExt.setAuditor_name(opUser.getName());
                inventoryExt.setAudit_date(new Date());
            } else if (state == -1) {
                inventoryExt.setState(StockConstants.STATE_UN_AUDIT);
                inventoryExt.setAuditor_sid(null);
                inventoryExt.setAuditor_name(null);
                inventoryExt.setAudit_date(null);
            }
            super.autoInjectBaseData(inventoryExt, opUser, this.TYPE_UPDATE);
        }

        ThreadPoolTaskUtil.executeInList4Split(billExtList, false, list -> jxcStockInventoryMapper.updateList(list));
    }

    @Override
    public void ReAuditJxcStockInventory(String sid, SysUser opUser, Integer state) throws Exception {
        JxcStockInventoryExt item = this.queryBySid(sid);
        super.autoInjectBaseData(item, opUser, this.TYPE_UPDATE_STOCK);
        Map<String, Object> params = new HashMap<>(8);
        params.put("inventory_sid", item.getSid());
        params.put("dr", 0);
        List<JxcStockInventoryItemExt> list = jxcStockInventoryItemService.queryGoodsByInventoryId(params);
        for (JxcStockInventoryItemExt jxcStockInventoryItemExt : list) {
            JxcStockGoodsExt jxcStockGoodsExt = jxcStockGoodsService.queryBySid(jxcStockInventoryItemExt.getStock_goods_sid());
            jxcStockGoodsExt.setStock_sum_qty(jxcStockInventoryItemExt.getCheck_qty());
            jxcStockGoodsService.saveJxcStockGoods(jxcStockGoodsExt, opUser);
        }
        item.setState(state);
        jxcStockInventoryMapper.auditJxcStockInventory(item);
    }

    @Override
    public void saveJxcStockInventory4Review(JxcStockInventoryExt inventoryExt, SysUser opUser) throws Exception {
        super.checkEmpty(inventoryExt.getId(), "请提供参数：id");
        JxcStockInventory old = jxcStockInventoryMapper.selectByPrimaryKey(inventoryExt.getId());
        if (2 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + "已复核");
//            throw new HlpException("盘点单：" + old.getCode() + " 已更新库存");
        }
        if (0 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + " 未审核，无法复核");
        }
        inventoryExt.setState(2);//复核
        // 保存数据
        this.saveJxcStockInventory(inventoryExt, opUser);

//        // 加入队列：更新 jxc_stock_goods_position 库存数量
//        jxcStockJob.addJxcStockQue("inventory", StockConstants.BIZ_NAME_INVENTORY, "updateStockQty2StockGoodsPosition4Inventory", inventoryExt.getId(), opUser);
    }

    @Override
    public void saveJxcStockInventory4UpdateStock(JxcStockInventoryExt inventoryExt, SysUserExt opUser) throws Exception {
        super.checkEmpty(inventoryExt.getId(), "请提供参数：id");
        JxcStockInventory old = jxcStockInventoryMapper.selectByPrimaryKey(inventoryExt.getId());

        if (StockConstants.UPDATE_STOCK.equals(old.getUpdate_stock())) {
            throw new HlpException("盘点单：" + old.getCode() + " 已更新库存");
        }
        if (0 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + " 未审核，无法更新库存");
        }
        if (1 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + " 已审核，未复核，无法更新库存");
        }
//        // 保存数据
//        this.saveJxcStockInventory(inventoryExt, opUser);

        // 加入队列：更新 jxc_stock_goods_position 库存数量
        jxcStockJob.addJxcStockQue("inventory", StockConstants.BIZ_NAME_INVENTORY, "updateStockQty2StockGoodsPosition4Inventory", inventoryExt.getId(), opUser);

    }

    @Override
    public List<JxcStockInventoryExt> queryJxcStockInventoryData4Print(List<String> sidList) throws Exception {
        List<JxcStockInventoryExt> list = ThreadPoolTaskUtil.queryInList4Split(sidList, itemList -> {
            JxcStockInventoryExt params = new JxcStockInventoryExt();
            params.setDr(0);
            params.setSid_list(itemList);
            return jxcStockInventoryMapper.selectByEntity(params);
        });
        if (!HlpUtils.isEmptyList(list)) {
            List<String> inventoryList = ListUtil.map(list, JxcStockInventoryExt::getSid);
            List<JxcStockInventoryItemExt> itemExtList = jxcStockInventoryItemService.queryByInventoryList(inventoryList);
            for (JxcStockInventoryExt inventoryExt : list) {
                List<JxcStockInventoryItemExt> filterList = ListUtil.filter(itemExtList, t -> t.getInventory_sid().equals(inventoryExt.getSid()));
                inventoryExt.setItem_list(filterList);
            }
        }
        return list;
    }

    @Override
    public void genJxcStockInventory4InOutBill(JxcStockInventoryExt inventoryExt, SysUserExt opUser) throws Exception {
        super.checkEmpty(inventoryExt.getId(), "请提供参数：id");
        JxcStockInventoryExt old = jxcStockInventoryMapper.selectBySid(inventoryExt.getSid());
        if (StockConstants.UPDATE_STOCK.equals(old.getUpdate_stock())) {
            throw new HlpException("盘点单：" + old.getCode() + " 已生成了出入库单");
        }
        if (0 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + " 未审核，无法生成了出入库单");
        }
        if (1 == old.getState()) {
            throw new HlpException("盘点单：" + old.getCode() + " 已审核，未复核，无法生成了出入库单");
        }
        // 1、获取盘点的明细，
        // 2、比较，盘亏需要生成出库单，盘盈需要生成入库单
        List<JxcStockInventoryItemExt> itemExtList = jxcStockInventoryItemService.queryByInventoryList(Collections.singletonList(old.getSid()));
        if (itemExtList == null || itemExtList.isEmpty()) {
            return;
        }
        List<JxcStockInventoryItemExt> surplusList = new ArrayList<>();
        List<JxcStockInventoryItemExt> lossList = new ArrayList<>();
        for (JxcStockInventoryItemExt itemExt : itemExtList) {
            if (!HlpUtils.isEmpty(itemExt.getSurplus()) && itemExt.getSurplus() > 0) {
                surplusList.add(itemExt);
            } else if (!HlpUtils.isEmpty(itemExt.getSurplus()) && itemExt.getSurplus() < 0) {
                lossList.add(itemExt);
            }
        }
        // 更新盘点单的是否成了出入库单
        old.setUpdate_stock(StockConstants.UPDATE_STOCK);
        old.setUpdate_stock_date(new Date());
        autoInjectBaseData(old, opUser, TYPE_UPDATE);
        jxcStockInventoryMapper.updateByPrimaryKeySelective(old);
        // 入库
        if (surplusList.size() > 0) {
            old.setSurplus_list(surplusList);
            JxcStockInbillExt inBillExt = old.genInBill(null);
            jxcStockInbillService.saveJxcStockInbill(inBillExt, opUser);
        }
        // 出库
        if (lossList.size() > 0) {
            old.setLoss_list(lossList);
            JxcStockOutbillExt outBillExt = old.genOutBill(null);
            jxcStockOutbillService.saveJxcStockOutbill(outBillExt, opUser);
        }
    }

}
